//
//  TaskHome.swift
//  SwiftUILean
//
//  Created by wyknmjj on 2024/5/14.
//

import SwiftUI
import Fakery

struct TaskHome:View {
    @State private var currentDate:Date = .init()
    @State private var weekSlider:[[Date.WeekDay]] = []
    @State private var currentWeekIndex = 1
    @State private var createWeek = false
    @State private var createNewTask = false
    @Namespace private var animation
    var body: some View {
        VStack(alignment: .leading,spacing: 0) {
                HeaderView()
            
            ScrollView(.vertical){
                VStack{
                    TasksView(currentDate: $currentDate)
                }.hSpacing(.center)
                .vSpacing(.center)
            }.scrollIndicators(.hidden)
        }.vSpacing(.top)
        .overlay(alignment: .bottomTrailing){
            Button{
                createNewTask.toggle()
            }label: {
                Image(systemName: "plus")
                    .fontWeight(.semibold)
                    .foregroundStyle(.white)
                    .frame(width: 55,height:55)
                    .background(.blue.shadow(.drop(color: .black.opacity(0.25), radius: 5, x:10, y:10)), in: .circle)
            }
            .padding(15)
        }
        .onAppear{
            if weekSlider.isEmpty{
                let cw = Date().fetchWeek()
                
                if let firstDate = cw.first?.date{
                    weekSlider.append(firstDate.createPreviousWeek())
                }
                
                weekSlider.append(cw)
                
                if let lastDate = cw.last?.date{
                    weekSlider.append(lastDate.createNextWeek())
                }
            }
        }.sheet(isPresented: $createNewTask){
            TaskNewView()
                .presentationDetents([.height(300)])
                .interactiveDismissDisabled()
                .presentationCornerRadius(30)
                .presentationBackground(.white)
        }
    }
    
    @ViewBuilder
    func HeaderView() -> some View{
        VStack(alignment: .leading,spacing: 6) {
            HStack(spacing:5){
                Text(currentDate.format("MMMM"))
                    .foregroundStyle(.blue)
                
                Text(currentDate.format("YYYY"))
                    .foregroundStyle(.gray)
                
            }
            .font(.title.bold())
            Text(currentDate.formatted(date: .complete, time: .omitted))
                .font(.callout)
                .fontWeight(.semibold)
                .textScale(.secondary)
                .foregroundStyle(.gray)
            
            
            TabView(selection: $currentWeekIndex) {
                ForEach(weekSlider.indices,id:\.self){index in
                        let week = weekSlider[index]
                    WeekView(week)
                        .padding(.horizontal,15)
                        .tag(index)
                }
            }.padding(.horizontal,-15)
                .tabViewStyle(.page(indexDisplayMode: .never))
            .frame(height: 90)
        }
        .hSpacing(.leading)
        .overlay(alignment: .topTrailing){
            Button{
                
            }label: {
                AsyncImage(url: URL(string: "https://loremflickr.com/200/200/paris,girl/all")!)
                    .aspectRatio(contentMode: .fill)
                    .frame(width: 45,height: 45)
                    .clipShape(.circle)
            }
        }
        .padding(15)
        .background(.white)
        .onChange(of: currentWeekIndex) { oldValue, newValue in
            if newValue == 0 || newValue == (weekSlider.count-1){
                createWeek=true
            }
            print("change",newValue)
        }
    }
    
    @ViewBuilder
    func WeekView(_ week:[Date.WeekDay]) -> some View{
        HStack(spacing:0){
            ForEach(week){day in
                VStack(spacing:8){
                    Text(day.date.format("E"))
                        .font(.callout)
                        .fontWeight(.medium)
                        .textScale(.secondary)
                        .foregroundStyle(.gray)
                    Text(day.date.format("dd"))
                        .font(.callout)
                        .fontWeight(.bold)
                        .textScale(.secondary)
                        .foregroundStyle(isSameDate(day.date, currentDate) ? .white : .gray)
                        .frame(width:35,height:35)
                        .background{
                            if isSameDate(day.date, currentDate){
                                Circle()
                                    .fill(.blue)
                                    .matchedGeometryEffect(id: "TABINDICATOR", in: animation)
                            }
                            if day.date.isToday {
                                Circle()
                                    .fill(.cyan)
                                    .frame(width: 5,height: 5)
                                    .vSpacing(.bottom)
                                    .offset(y: 12)
                            }
                        }
                        .background(.white.shadow(.drop(radius: 1)), in: .circle)
                }
                .hSpacing(.center)
                .contentShape(.rect)
                .onTapGesture {
                    withAnimation(.snappy) {
                        currentDate = day.date
                    }
                }
            }
        }
        .background{
            GeometryReader{
                let minX = $0.frame(in: .global).minX
                Color.clear
                    .preference(key: TaskOffsetKey.self, value: minX)
                    .onPreferenceChange(TaskOffsetKey.self){value in
                        /**
                         在react里一般是状态驱动,到达某个页面,生成前后两个页面
                         这里却是事件驱动,也是能观察到事件变化
                          但应该在动画表演完成之后,否则应该有个基于key的突变
                         */
                        if value.rounded()==15 && createWeek {
                            print("Generate week")
                            createWeek=false
                            paginateWeek()
                        }
                    }
            }
        }
    }
    
    func paginateWeek(){
        if weekSlider.indices.contains(currentWeekIndex){
            if let firstDate = weekSlider[currentWeekIndex].first?.date,
               currentWeekIndex == 0{
                weekSlider.insert(firstDate.createPreviousWeek(), at: 0)
                weekSlider.removeLast()
                currentWeekIndex += 1
            }
            if let lastDate = weekSlider[currentWeekIndex].last?.date,
               currentWeekIndex == weekSlider.count-1{
                weekSlider.append(lastDate.createPreviousWeek())
                weekSlider.removeFirst()
                currentWeekIndex -= 1
            }
        }
    }
}



#Preview {
    TaskHome()
}
